#ifndef  __EDITCOMMAND_H__
#define  __EDITCOMMAND_H__

#include "seq/VisCommand.h"
#include "seq/SeqCommand.h"
#include "seq/Event.h"

#include <boost/shared_ptr.hpp>

namespace editor {

enum EditCommandTypes {
    EDIT_CMD_JUMP         = 101,
    EDIT_CMD_EVENT_JUMP   = 102,
    EDIT_CMD_ADD_SCREEN   = 103,
    EDIT_CMD_DEL_SCREEN   = 104,
    EDIT_CMD_CHG_CATEGORY = 105,
    EDIT_CMD_CHG_TRACK    = 106
};

enum EditCmdTagTypes {
    EDIT_CMDTAG_CHANGE_NOTELEN     = 901,
    EDIT_CMDTAG_CHANGE_VELOCITY    = 902,
    EDIT_CMDTAG_CHANGE_ONEINTVALUE = 903,
    EDIT_CMDTAG_CHANGE_TEXT        = 904
};

class JumpCommand : public seq::VisCommand {
public:
    JumpCommand(int id, seq::ListCategory category, unsigned tick, unsigned keyPos);
    virtual ~JumpCommand();

    virtual void execute(seq::Project& p);
    virtual void undo(seq::Project& p);
    virtual int typeID() const;
private:
    int       screenID_;
    seq::ListCategory category_;
    unsigned  tick_;
    unsigned  keyPos_;

    int       oldScreenID_;
    seq::ListCategory oldCategory_;
    unsigned  oldTick_;
    unsigned  oldKeyPos_;
};

class JumpEventCommand : public seq::VisCommand {
public:
    JumpEventCommand(int id, seq::ListCategory category, unsigned tick);
    virtual ~JumpEventCommand();

    virtual void execute(seq::Project& p);
    virtual void undo(seq::Project& p);
    virtual int typeID() const;
private:
    int       screenID_;
    seq::ListCategory category_;
    unsigned  tick_;

    int       oldScreenID_;
    seq::ListCategory oldCategory_;
    unsigned  oldTick_;
};

class EditCmdTag : public seq::VisCommand {
public:
    EditCmdTag() {}
    virtual ~EditCmdTag() {}
    virtual void execute(seq::Project& p) {}
    virtual void undo(seq::Project& p) {}
    virtual int typeID() const = 0;
};

class ChangeNoteLenTag : public EditCmdTag {
public:
    ChangeNoteLenTag(const boost::shared_ptr<seq::ChangeCommand>& pCmd) :
        pCmd_(pCmd)
    {}
    virtual ~ChangeNoteLenTag() {}
    virtual int typeID() const {return EDIT_CMDTAG_CHANGE_NOTELEN;}
    const seq::EventPtr& oldEvent() const {return pCmd_->oldEvent();}
    const seq::EventPtr& newEvent() const {return pCmd_->newEvent();}
    seq::ListCategory listCategory() const {return pCmd_->listCategory();}
    unsigned tick() const {return pCmd_->tick();}
private:
    boost::shared_ptr<seq::ChangeCommand> pCmd_;
};

class ChangeVelocityTag : public EditCmdTag {
public:
    ChangeVelocityTag(const boost::shared_ptr<seq::ChangeCommand>& pCmd) :
        pCmd_(pCmd)
    {}
    virtual ~ChangeVelocityTag() {}
    virtual int typeID() const {return EDIT_CMDTAG_CHANGE_VELOCITY;}
    const seq::EventPtr& oldEvent() const {return pCmd_->oldEvent();}
    const seq::EventPtr& newEvent() const {return pCmd_->newEvent();}
    seq::ListCategory listCategory() const {return pCmd_->listCategory();}
    unsigned tick() const {return pCmd_->tick();}
private:
    boost::shared_ptr<seq::ChangeCommand> pCmd_;
};

class ChangeOneIntValueEventTag : public EditCmdTag {
public:
    ChangeOneIntValueEventTag(const boost::shared_ptr<seq::ChangeCommand>& pCmd) :
        pCmd_(pCmd)
    {}
    virtual ~ChangeOneIntValueEventTag() {}
    virtual int typeID() const {return EDIT_CMDTAG_CHANGE_ONEINTVALUE;}
    const seq::EventPtr& oldEvent() const {return pCmd_->oldEvent();}
    const seq::EventPtr& newEvent() const {return pCmd_->newEvent();}
    seq::ListCategory listCategory() const {return pCmd_->listCategory();}
    unsigned tick() const {return pCmd_->tick();}
private:
    boost::shared_ptr<seq::ChangeCommand> pCmd_;
};

class ChangeTextValueEventTag : public EditCmdTag {
public:
    ChangeTextValueEventTag(const boost::shared_ptr<seq::ChangeCommand>& pCmd) :
        pCmd_(pCmd)
    {}
    virtual ~ChangeTextValueEventTag() {}
    virtual int typeID() const {return EDIT_CMDTAG_CHANGE_TEXT;}
    const seq::EventPtr& oldEvent() const {return pCmd_->oldEvent();}
    const seq::EventPtr& newEvent() const {return pCmd_->newEvent();}
    seq::ListCategory listCategory() const {return pCmd_->listCategory();}
    unsigned tick() const {return pCmd_->tick();}
private:
    boost::shared_ptr<seq::ChangeCommand> pCmd_;
};

class AddScreenCommand : public seq::VisCommand {
public:
    AddScreenCommand();
    AddScreenCommand(int baseID);
    virtual ~AddScreenCommand();

    virtual void execute(seq::Project& p);
    virtual void undo(seq::Project& p);
    virtual int typeID() const {return EDIT_CMD_ADD_SCREEN;}
private:
    int baseID_;
    int id_;
};

class DelScreenCommand : public seq::VisCommand {
public:
    DelScreenCommand();
    DelScreenCommand(int id);
    virtual ~DelScreenCommand();

    virtual void execute(seq::Project& p);
    virtual void undo(seq::Project& p);
    virtual int typeID() const {return EDIT_CMD_DEL_SCREEN;}
private:
    int       id_;
};

#if 0
class ChgCategoryCommand : public seq::VisCommand {
public:
    ChgCategoryCommand();
    ChgCategoryCommand(seq::ListCategory category);
    ChgCategoryCommand(int id, seq::ListCategory category);
    virtual ~ChgCategoryCommand();

    virtual void execute(seq::Project& p);
    virtual void undo(seq::Project& p);
    virtual int typeID() const {return EDIT_CMD_CHG_CATEGORY;}
private:
    int       id_;
    seq::ListCategory category_;
    seq::ListCategory oldCategory_;
};

class ChgTrackCommand : public seq::VisCommand {
public:
    ChgTrackCommand();
    ChgTrackCommand(int trackNo);
    ChgTrackCommand(int id, int trackNo);
    virtual ~ChgTrackCommand();

    virtual void execute(seq::Project& p);
    virtual void undo(seq::Project& p);
    virtual int typeID() const {return EDIT_CMD_CHG_TRACK;}
private:
    int id_;
    int trackNo_;
    int oldTrackNo_;
};
#endif

} // end of namespace editor

#endif   /* ----- #ifndef __EDITCOMMAND_H__  ----- */
